﻿console.log("eswebsocket.js begins");

export const Es_Websocket = (function () {
  var browserInfo = {};
  var g_strCurFunc = "";
  var g_response = null;
  var esUsbKey = "";
  var g_isLoad = false;
  var g_IeOrLowVer = false; // ie或者支持npapi的非ie浏览器

  function IsWindows() {
    if (/windows|win32/i.test(navigator.userAgent)) {
      return true;
    } else {
      return false;
    }
  }

  function IsMac() {
    if (/macintosh|mac os x/i.test(navigator.userAgent)) {
      return true;
    } else {
      return false;
    }
  }

  function IsLinux() {
    if (String(navigator.platform).indexOf("Linux") > -1) {
      return true;
    } else {
      return false;
    }
  }

  function GetBrowserInfo() {
    var Sys = {};
    var ua = navigator.userAgent.toLowerCase();
    var re = /(msie|firefox|chrome|opera|version).*?([\d.]+)/;
    var m = ua.match(re);

    Sys.browser = "";
    Sys.ver = 0;
    if (null == m || undefined == m) {
      return Sys;
    }

    Sys.browser = m[1].replace(/version/, "safari");
    Sys.ver = parseInt(m[2], 10);
    return Sys;
  }

  function IsIe() {
    if (!!window.ActiveXObject || "ActiveXObject" in window) {
      return true;
    } else {
      return false;
    }
  }

  function IsChrome42Plus() {
    if ("chrome" == browserInfo.browser && 42 <= browserInfo.ver) {
      return true;
    } else {
      return false;
    }
  }

  function IsFirefox52Plus() {
    if ("firefox" == browserInfo.browser && 52 <= browserInfo.ver) {
      return true;
    } else {
      return false;
    }
  }

  function IsSafari12Plus() {
    if ("safari" == browserInfo.browser && 12 <= browserInfo.ver) {
      return true;
    }
    return false;
  }

  function IsEdge() {
    // edge 可能模拟为chrome和safari，GetBrowserInfo获取到的可能是chrome
    if (navigator.userAgent.indexOf("Edge") > -1) {
      browserInfo.browser = "edge";
      return true;
    } else {
      return false;
    }
  }

  function esKeyInitialize() {
    if (g_isLoad) {
      return;
    }
    g_isLoad = true;
  }

  // 组织响应数据
  function callBackFunction(funcName, response) {
    try {
      if (funcName == g_strCurFunc) {
        // 切成两部分
        var s = response.split("---");
        var ret = s[0]; // 执行结果
        var retData = "";
        if (s.length > 1 && s[1].length > 0) {
          retData = s[1]; // 响应数据
        }

        g_response = {action: funcName, result: ret, responseData: retData};
      } else {
        funcName = g_strCurFunc;
        g_response = {action: funcName, result: "E0600007", responseData: ""};
      }
    } catch (e) {
      g_response = {action: funcName, result: "E0600007", responseData: ""};
    }
  }

  function DelayFunc(funcName, useWS) {
    // 接收服务端数据时触发事件
    if (useWS) {
      ws.onmessage = function (event) {
        var data = eval('(' + event.data + ')');
        var cmd = data.Type;
        var response = data.StringResult;

        callBackFunction(cmd, response);
        ws.onmessage = null;
      };
    } else {
      window.addEventListener("message", function handleNativeMessage(event) {
        if (event.source != window) {
          return;
        }

        var cmd = event.data.type;
        var response = event.data.text;
        callBackFunction(cmd, response);
        window.removeEventListener(event.type, handleNativeMessage);
      }, false);
    }
  }

  // 初始化一个 WebSocket 对象
  // 注意!不同项目使用的端口号必须不一样
  var STD_PORT = 28888; // 使用的接口必须和websocket服务端监听的端口一致，请根据项目实际情况修改
  var ws = null;
  var wsError = false;

  // WebSocket连接被关闭时触发
  function onWsClose() {
    console.log("WebSocket连接已关闭...");
    ws = null;
    wsError = true;
  };

  function onWsError() {
    console.log("WebSocket错误...");
    wsError = true;
  }

  function WsSend(wsocket, funcName, data) {
    wsocket.send(data);
    DelayFunc(funcName, true);
  }

  function Callxx(funcName, input) {
    return new Promise(function (resolve, reject) {
      try {
        var strData = JSON.stringify(input);

        if (g_strCurFunc.length > 0) {
          // reject("前一个操作尚未完成，请稍后再试。");
          reject("WEBSOCKET_PLUGIN_BUSY");
          return;
        }

        wsError = false;
        if (IsSafari12Plus()) {
          var event = new CustomEvent('EsStdSafariExtensionSendMsg', {'detail': strData});
          window.dispatchEvent(event);
          DelayFunc(funcName, false);
        } else {
          if (!ws || 1 != ws.readyState) {
            console.log("准备建立WebSocket连接...");
            ws = new WebSocket("ws://127.0.0.1:" + STD_PORT);
            ws.onclose = onWsClose;
            ws.onerror = onWsError;

            ws.addEventListener('open', function (event) {
              ws.onopen = null;
              WsSend(ws, funcName, strData);
            });
          } else {
            WsSend(ws, funcName, strData);
          }
        }

        g_response = null;
        g_strCurFunc = funcName;
        var check = setInterval(function () {
          if (wsError) {
            g_strCurFunc = "";
            g_response = null;
            clearInterval(check);
            // reject("接收数据异常，请确认本地WebSocket服务器已启动后重试 ");
            reject("NO_WEBSOCKET_PLUGIN");
            return;
          }
          if (g_response) {
            var data = g_response;

            g_strCurFunc = "";
            g_response = null;

            clearInterval(check);

            // 根据错误码来决定是抛出异常还是正确结果
            if (0 == parseInt(data.result, 16)) {
              resolve(data.responseData);
            } else {
              reject(data.result);
            }
            return;
          }
        }, 20);
      } catch (e) {
        reject(e);
        return;
      }
    });
  }

  function promiseExit() {
    // 简单粗暴地终止后续的then调用
    return new Promise(function () {
    });
  }

  // ie/npapi版本获取错误信息
  // 优先从接口内获取，不然就使用入参传入的之前捕获的异常信息
  function IeOrLowVergetErrorMsg(esObj, e) {
    var errMsg;
    var type = typeof (e.message);

    if ("string" == type) {
      errMsg = e.message;
    } else if ("string" == typeof (e)) {
      errMsg = e;
    } else {
      errMsg = "";
    }

    try {
      var err = esObj.esGetErrorMessage();
      if (err.length > 0) {
        errMsg = err;
      }
    } catch (err) {
    }

    return errMsg;
  }

  function esSendApdu(seid, req) {
    var ret;
    try {
      var funName = "esSendApdu";
      var input = {"Type": funName, "seid": seid, "Apdu": req};
      ret = Callxx(funName, input);
    } catch (e) {
      return;
    } finally {
      return ret;
    }
  }

  function esKeyEnum() {
    var ret;
    try {
      var funName = "esEnumDev";
      var input = {"Type": funName};
      ret = Callxx(funName, input);
    } catch (e) {
      return;
    } finally {
      return ret;
    }
  }

  function esGetVersion() {
    var ret;
    try {
      var funName = "esGetVersion";
      var input = {"Type": funName};
      ret = Callxx(funName, input);
    } catch (e) {
      return;
    } finally {
      return ret;
    }
  }

  return {
    getVersion: function () {
      return esGetVersion();
    },
    keyEnum: function () {
      return esKeyEnum();
    },
    sendApdu: function (seid, req) {
      return esSendApdu(seid, req);
    },
    isWindows: function () {
      return IsWindows();
    },
    isMacOS: function () {
      return IsMac();
    },
    isLinux: function () {
      return IsLinux();
    }
  };

})();

console.log("eswebsocket.js ends");
